﻿// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证（版本 2.0）进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动！任何基于本项目二次开发而产生的一切法律纠纷和责任，我们不承担任何责任！

using Admin.NET.Application.Entity;
using Aop.Api.Domain;
using Furion.Logging;
using Newtonsoft.Json;
using System.Data;
using WCS.Application.Entity.Warehous;
using WCS.Application.Service.Materialssuance;

namespace Admin.NET.Application.Service.OrderInfo;
/// <summary>
/// 出入库订单
/// </summary>
[ApiDescriptionSettings(groups: ApplicationConst.GroupName, Order = 11)]
[AllowAnonymous]
public class OrderInfoService : IDynamicApiController, ITransient
{

    private readonly SqlSugarRepository<OrderInfoEntity> _orderInfoRep;
    private readonly SqlSugarRepository<OrderDetailEntity> _orderDetailRep;
    private readonly SqlSugarRepository<WCSTaskManagementEntity> _wcsTaskEntity;
    private readonly SqlSugarRepository<InventoryManagementEntity> _stock;
    private readonly UserManager _userinfo;

    public OrderInfoService(
        SqlSugarRepository<OrderInfoEntity> orderInfoRep,
        SqlSugarRepository<OrderDetailEntity> orderDetailRep,
        SqlSugarRepository<WCSTaskManagementEntity> wcsTaskEntity,
        SqlSugarRepository<InventoryManagementEntity> stock,
    UserManager userinfo
        )
    {
        _userinfo = userinfo;
        _orderInfoRep = orderInfoRep;
        _orderDetailRep = orderDetailRep;
        _stock = stock;
        _wcsTaskEntity = wcsTaskEntity;
    }

    /// <summary>
    /// 获取分页订单信息 🔖
    /// </summary>
    /// <param name="Orderinput"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "GetOrderPageList"), HttpPost]
    public async Task<SqlSugarPagedList<OrderInfoEntity>> GetOrderPageList(OrderInfoDto Orderinput)
    {
        SerilogHelper.WriteLog("UpdateOrderInfo——查询分页订单开始" + JsonConvert.SerializeObject(Orderinput));

        var list = await _orderInfoRep.AsQueryable()
         .WhereIF(!string.IsNullOrWhiteSpace(Orderinput.OrderId), u => u.OrderId.Contains(Orderinput.OrderId))
         .WhereIF(!string.IsNullOrWhiteSpace(Orderinput.OrderType.ToString()), u => u.OrderType.Equals(Orderinput.OrderType))
         .WhereIF(!string.IsNullOrWhiteSpace(Orderinput.OrderStatus.ToString()), u => u.OrderStatus.Equals(Orderinput.OrderStatus))
            .OrderBuilder(Orderinput)
            .ToPagedListAsync(Orderinput.Page, Orderinput.PageSize);
        SerilogHelper.WriteLog("UpdateOrderInfo——查询分页订单结束" + JsonConvert.SerializeObject(list));

        return list;
    }


    /// <summary>
    /// 获取订单信息 🔖
    /// </summary>
    /// <param name="Orderinput"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "GetOrderList"), HttpPost]
    public async Task<List<OrderInfoEntity>> GetOrderList(OrderInfoDto Orderinput)
    {
        SerilogHelper.WriteLog("UpdateOrderInfo——查询订单开始" + JsonConvert.SerializeObject(Orderinput));

        Expression<Func<OrderInfoEntity, bool>> expression = whereExp =>
                 (Orderinput.OrderId.GetIsEmptyOrNull() || whereExp.OrderId.Contains((Orderinput.OrderId.Trim())))
                 && (Orderinput.MaterialCode.GetIsEmptyOrNull() || whereExp.OrderId.Contains((Orderinput.MaterialCode.Trim())))
                 && (Orderinput.OrderStatus.GetIsEmptyOrNull() || whereExp.OrderStatus.Equals(Orderinput.OrderStatus))
                 && (Orderinput.OrderType.GetIsEmptyOrNull() || whereExp.OrderType.Equals(Orderinput.OrderType))
                 ;

        var list = await _orderInfoRep.AsQueryable().WhereIF(expression != null, expression).OrderBuilder(Orderinput).ToListAsync();
        SerilogHelper.WriteLog("UpdateOrderInfo——查询订单结束" + JsonConvert.SerializeObject(list));

        return list;
    }

    /// <summary>
    /// 新增订单
    /// </summary>
    /// <param name="OrderInfoDto"></param>
    /// <returns></returns>
    [UnitOfWork]
    [ApiDescriptionSettings(Name = "InsertOrderInfo"), HttpPost]
    public async Task<long> InsertOrderInfo(AddOrderInfoInput OrderInfoDto)
    {
        #region 唯一索引
        Expression<Func<OrderInfoEntity, bool>> whereExpression = whereExp =>
                   whereExp.OrderId.Equals(OrderInfoDto.OrderId);
        var data = await _orderInfoRep.GetFirstAsync(whereExpression);
        if (data != null)
        {
            throw Oops.Oh("该记录已存在");
        }
        #endregion

        OrderInfoEntity orderInfoEntity = new OrderInfoEntity
        {
            OrderId = OrderInfoDto.OrderId,
            OrderType = OrderTypeEnum.OutBound1,
            OrderStatus = OrderStatusEnum.Panding,
        };
        var rtInsert = await _orderInfoRep.AsInsertable(orderInfoEntity).ExecuteCommandAsync();

        List<OrderDetailEntity> orderDetails = new List<OrderDetailEntity>();
        foreach (var item in OrderInfoDto.Tray)
        {
            orderDetails.Add(new OrderDetailEntity
            {
                SerialNumber = "1",
                PickingNumber = OrderInfoDto.OrderId.GetCString(),
                Tray = item.GetCString(),
                EntranceandExit = OrderInfoDto.HoistOpening.GetCString()
            });
        }
        //OrderDetailEntity orderDetail = new OrderDetailEntity
        //{
        //    SerialNumber = "1",
        //    PickingNumber = OrderInfoDto.OrderId.GetCString(),
        //    Tray = OrderInfoDto.Tray.GetCString(),
        //    EntranceandExit = OrderInfoDto.HoistOpening.GetCString()
        //};
        var dataDetail = await _orderDetailRep.AsInsertable(orderDetails).ExecuteCommandAsync();
        if (dataDetail!= orderDetails.Count())
        {
            throw Oops.Oh("添加失败!");
        }
        return dataDetail;
    }

    /// <summary>
    /// 执行订单
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "ExecuteOrder"), HttpPost]
    [DisplayName("执行订单")]
    public async Task ExecuteOrder(DeleteOrderInfoDtoInput input)
    {
        #region "校验唯一索引"
        Expression<Func<OrderInfoEntity, bool>> whereExpression = whereExp =>
                    whereExp.Id.Equals(input.Id);
        #endregion    
        var entity = await _orderInfoRep.GetFirstAsync(whereExpression) ?? throw Oops.Oh("订单不存在");
        if (entity.OrderStatus == OrderStatusEnum.Panding || entity.OrderStatus == OrderStatusEnum.Pause)
        {

            entity.OrderStatus = OrderStatusEnum.Onging;
            await _orderInfoRep.AsUpdateable(entity).UpdateColumns(it => it.OrderStatus).ExecuteCommandAsync();

            Expression<Func<OrderDetailEntity, bool>> detailWhere = whereExp =>
                whereExp.PickingNumber.Equals(entity.OrderId)
                ;
            var dataDetails = await _orderDetailRep.Context.CopyNew().Queryable<OrderDetailEntity>().Where(detailWhere).ToListAsync();
            // 注册雪花Id
            var snowIdOpt = App.GetConfig<SnowIdOptions>("SnowId", true);
            YitIdHelper.SetIdGenerator(snowIdOpt);
            Random random = new Random();

            var v_i = 1;
            foreach (var detail in dataDetails)
            {
                if (detail.Status == 0 || detail.Status == 3)
                {
                    var locStatus = await _stock.AsQueryable().Where(it => it.Palcode == detail.Tray && it.Status == InventoryStatus.正常).FirstAsync();
                    if (locStatus != null)
                    {
                        // 修改明细状态为执行
                        detail.Status = (int)OrderStatusEnum.Onging;
                        
                        // 写入wcs任务表
                        var wcsTask = new WCSTaskManagementEntity()
                        {
                            TaskNumber = entity.OrderId + v_i.ToString().PadLeft(4, '0'),
                            Type = TaskTypeEnum.Outbound,
                            Status = TaskStatusEnmu.NoStarte,
                            OrderId = entity.OrderId,
                            Loc = locStatus.WarehousePositionCode,
                            HoistOpening = detail.EntranceandExit,
                            TrayCode = detail.Tray,
                        };
                        var rtInsertTask = await _wcsTaskEntity.AsInsertable(wcsTask).ExecuteCommandAsync();
                    }
                    else
                    {
                        // 修改明细状态为异常
                        detail.Status = (int)OrderStatusEnum.Error;

                    }

                    var rtUpdateDetail = await _orderDetailRep.Context.CopyNew().Updateable<OrderDetailEntity>(detail).ExecuteCommandAsync();
                    var rtUpdateDetail1 = await _orderDetailRep.AsUpdateable(detail).ExecuteCommandAsync();
                    v_i++;
                }
            }
        }
        else
        {
            throw Oops.Oh("订单状态不允许下发执行");
        }
    }


    /// <summary>
    /// 暂停订单
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "PauseOrder"), HttpPost]
    [DisplayName("暂停订单")]
    public async Task PauseOrder(DeleteOrderInfoDtoInput input)
    {
        #region "校验唯一索引"
        Expression<Func<OrderInfoEntity, bool>> whereExpression = whereExp =>
                    whereExp.Id.Equals(input.Id);
        #endregion    
        var entity = await _orderInfoRep.GetFirstAsync(whereExpression) ?? throw Oops.Oh("订单不存在");
        if (entity.OrderStatus == OrderStatusEnum.Onging)
        {

            entity.OrderStatus = OrderStatusEnum.Pause;
            await _orderInfoRep.AsUpdateable(entity).UpdateColumns(it => it.OrderStatus).ExecuteCommandAsync();


            // 修改明细状态为暂停
            Expression<Func<OrderDetailEntity, bool>> detailWhere = whereExp =>
                whereExp.PickingNumber.Equals(entity.OrderId)
                ;
            var dataDetails = await _orderDetailRep.AsQueryable().Where(detailWhere).ToListAsync();
            foreach (var detail in dataDetails)
            {
                if (detail.Status == 1)
                {
                    detail.Status = (int)OrderStatusEnum.Pause;
                    var rtUpdateDetail = await _orderDetailRep.AsUpdateable(detail).ExecuteCommandAsync();
                }
            }


            // 修改WCS任务表，暂停

        }
        else
        {
            throw Oops.Oh("订单状态不允许下发执行");
        }
    }

    /// <summary>
    /// 删除订单信息🔖
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "DeleteOrder"), HttpPost]
    [DisplayName("删除订单")]
    public async Task DeleteOrder(DeleteOrderInfoDtoInput input)
    {
        #region "校验唯一索引"
        Expression<Func<OrderInfoEntity, bool>> whereExpression = whereExp =>
                    whereExp.Id.Equals(input.Id);
        #endregion    
        var entity = await _orderInfoRep.GetFirstAsync(whereExpression) ?? throw Oops.Oh(ErrorCodeEnum.D1002);
        if (entity.OrderStatus == OrderStatusEnum.Onging)
        {
            throw Oops.Oh("订单进行中，不允许删除");
        }
        else
        {
            await _orderInfoRep.DeleteAsync(entity); // 假删除
            //await _rep.DeleteAsync(entity); // 真删除
        }
    }

    /// <summary>
    /// 批量删除
    /// </summary>
    /// <param name="inputList"></param>
    /// <returns></returns>
    [UnitOfWork]
    [ApiDescriptionSettings(Name = "BatchDeleteOrderInfo"), HttpDelete]
    [DisplayName("批量删除")]
    public virtual async Task<int> BatchDeleteOrderInfo(List<DeleteOrderInfoDtoInput> inputList)
    {
        #region "校验"
        foreach (var input in inputList)
        {
            Expression<Func<OrderInfoEntity, bool>> whereExpression = whereExp =>
                        whereExp.Id.Equals(input.Id)
                   ;
            var data = await _orderInfoRep.GetFirstAsync(whereExpression);
            if (data == null)
            {
                throw Oops.Oh("该记录不存在");
            }
            else
            {
                if( data.OrderStatus == OrderStatusEnum.Onging)
                {
                    throw Oops.Oh("订单进行中，不允许删除");
                }
            }

        }
        #endregion

        var deleteEntity = inputList.Adapt<List<OrderInfoEntity>>();
        return await _orderInfoRep.AsDeleteable()
            .Where(deleteEntity)
            .ExecuteCommandAsync();
    }

    /// <summary>
    /// 下载模版
    /// </summary>
    /// <returns></returns>
    [UnitOfWork]
    [DisplayName("下载模版")]
    public virtual async Task<IActionResult> DownloadOrderTemplate()
    {
        return await Task.Run(() =>
        {
            #region "校验"
            string fileName = "OrderinfoTemplate.xlsx";
            string filePath = $"{AppDomain.CurrentDomain.BaseDirectory}/Template/{fileName}";
            if (!File.Exists(filePath))
            {
                throw Oops.Oh(10002, "找不到该模板：" + filePath);
            }
            #endregion

            var path = Path.Combine(filePath);
            return new FileStreamResult(new FileStream(path, FileMode.Open), System.Net.Mime.MediaTypeNames.Application.Octet)
            {
                FileDownloadName = fileName
            };
        });
    }

    /// <summary>
    /// 导出订单
    /// </summary>·
    [UnitOfWork]
    [DisplayName("导出Orderinfo")]
    [ApiDescriptionSettings(Name = "OrderExport"), HttpPost]
    public virtual async Task<IActionResult> OrderExport(ExportOrderInfoInput input)
    {
        Expression<Func<OrderInfoEntity, bool>> whereExpression = whereExp =>
                   (input.OrderId.GetIsEmptyOrNull() || whereExp.OrderId.Contains(input.OrderId.Trim()))
                   && (input.OrderStatus.GetIsEmptyOrNull() || whereExp.OrderStatus.Equals(input.OrderStatus))
                   && (input.OrderType.GetIsEmptyOrNull() || whereExp.OrderType.Equals(input.OrderType))
                   && (input.OrderStatus.GetIsEmptyOrNull() || whereExp.OrderStatus.Equals(input.OrderStatus));


        //排序默认id正序 asc OrderBuilder(input)
        var list = await _orderInfoRep.AsQueryable()
           .WhereIF(whereExpression != null, whereExpression).OrderBuilder(input)
           .ToListAsync();
        string path = AppDomain.CurrentDomain.BaseDirectory + "Export";
        if (!Directory.Exists(path))
        {
            Directory.CreateDirectory(path);
        }
        IExcelExporter excelExporter = new ExcelExporter();



        var res = await excelExporter.ExportAsByteArray(list);
        return new FileStreamResult(new MemoryStream(res), "application/octet-stream") { FileDownloadName = $"OrderExport_{DateTime.Now.ToString("yyyyMMddHHmmss")}_{new Random().Next(10000000, 99999999)}.xlsx" };
    }


    /// <summary>
    /// 导入订单(暂存出库)
    /// </summary>
    /// <param name="file"></param>
    /// <returns></returns>
    [UnitOfWork]
    [DisplayName("导入订单(暂存出库)")]
    [ApiDescriptionSettings(Name = "ImportOrderinfo"), HttpPost]
    public virtual async Task<List<ImportOrderInfoOutput>> ImportOrderinfo([Required] IFormFile file)
    {

        if (file != null)
        {
            var fileDir = AppDomain.CurrentDomain.BaseDirectory + @"ImportFile";
            if (!Directory.Exists(fileDir))

            {
                Directory.CreateDirectory(fileDir);
            }
            //文件名称
            string fileName = file.FileName;
            //文件类型
            string fileType = file.FileName.Substring(fileName.LastIndexOf("."));
            //上传的文件的路径
            string filePath = fileDir + $@"/{fileName}";
            if (File.Exists(filePath))
            {
                File.Delete(filePath);
            }
            using (FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite))
            {
                file.CopyTo(fs);
            }

            if (fileType == ".xlsx" || fileType == ".xls")
            {
                ExcelHelper eh = new ExcelHelper(filePath);
                DataTable dt = eh.ExcelToDataTable("", true);
                eh.Dispose();
                if (dt == null || dt.Rows.Count == 0)
                {
                    throw Oops.Oh("文件为空！");
                }


                #region "校验模板字段"
                if (!dt.Columns.Contains("序号") || !dt.Columns.Contains("单号") || !dt.Columns.Contains("库位码") || !dt.Columns.Contains("出库口"))
                {
                    throw Oops.Oh("文件模板错误！请重新下载模板");
                }
                var orderid = string.Empty;

                //不存在订单编号自己生成
                Random random = new Random();
                orderid = "MOVE" + DateTime.Now.ToString("yyyyMMddHHmmss") + random.Next(0, 9999);

                #endregion

                // 查询所有订单
                var allOrderList = await _orderInfoRep.AsQueryable().ToListAsync();
                var allOrder = allOrderList.ToDictionary(it => it.OrderId, it => it.OrderId);
                var allOrderInsert = new Dictionary<string,string>();


                List<ImportOrderInfoOutput> listOrderLoad = new List<ImportOrderInfoOutput>();
                List<ImportOrderDetailOutput> listOrderDetailLoad = new List<ImportOrderDetailOutput>();
                foreach (DataRow row in dt.Rows)
                {
                    //校验关联信息是否正确仓库代码
                    ImportOrderInfoOutput orderInfoEntity = new ImportOrderInfoOutput
                    {
                        OrderId = row["单号"].GetIsEmptyOrNull() ? orderid : row["单号"].GetCString(),
                        OrderType = OrderTypeEnum.OutBound1,
                        OrderStatus = OrderStatusEnum.Panding,
                    };
                    if (allOrder.ContainsKey(orderInfoEntity.OrderId))
                    {
                        throw Oops.Oh("订单号已存在");
                    }
                    if (!allOrderInsert.ContainsKey(orderInfoEntity.OrderId))
                    {
                        var insertRt = await _orderInfoRep.AsInsertable(orderInfoEntity).ExecuteCommandAsync();
                        SerilogHelper.WriteLog("ImportOrderinfo", "insertRt", insertRt.ToString());
                        allOrderInsert.Add(orderInfoEntity.OrderId, orderInfoEntity.OrderId);
                    }

                    ImportOrderDetailOutput orderDetail = new ImportOrderDetailOutput
                    {
                        SerialNumber = row["序号"].GetCString(),
                        PickingNumber = row["单号"].GetIsEmptyOrNull() ? orderid : row["单号"].GetCString(),
                        Tray = row["库位码"].GetCString(),
                        EntranceandExit = row["出库口"].GetCString(),
                    };

                    Expression<Func<OrderDetailEntity, bool>> whereExpression = whereExp =>
                        whereExp.PickingNumber.Equals(orderInfoEntity.OrderId)
                        && whereExp.Tray.Equals(orderDetail.Tray)
                        ;
                    var dataDetail = await _orderDetailRep.GetFirstAsync(whereExpression);
                    if (dataDetail is null)
                    {
                        var insertDetailRt = await _orderDetailRep.AsInsertable(orderDetail).ExecuteCommandAsync();
                        SerilogHelper.WriteLog("ImportOrderinfo", "insertDetailRt", insertDetailRt.ToString());
                    }

                }

                //var rtOrderInsert = await _orderInfoRep.Context.Fastest<OrderInfoEntity>().BulkCopyAsync(listOrderLoad.Adapt<List<OrderInfoEntity>>());
                //SerilogHelper.WriteLog("ImportOrderinfo", "rtOrderInsert", JsonHelper.ObjectToJson(rtOrderInsert));
                //var rtOrderDetailInsert = await _orderDetailRep.Context.Fastest<OrderDetailEntity>().BulkCopyAsync(listOrderDetailLoad.Adapt<List<OrderDetailEntity>>());
                //SerilogHelper.WriteLog("ImportOrderinfo", "rtOrderDetailInsert", JsonHelper.ObjectToJson(rtOrderDetailInsert));

            }
            else
            {
                throw Oops.Oh(10002, "文件内容为空！");
            }
        }
        else
        {
            throw Oops.Oh(10002, "请选择文件！");
        }
        return null;
    }


    /// <summary>  
    /// 生成订单号（当前时间+流水号）  
    /// </summary>  
    /// <returns></returns>  
    public async Task<string> GenerateOrderIdAsync()
    {
        var currentDate = DateTime.Now.ToString("yyyyMMddHHmmss");
        var maxOrderId = await _orderInfoRep.AsQueryable()
            .Where(o => o.OrderId.StartsWith(currentDate))
            .MaxAsync(o => o.OrderId);

        var sequenceNumber = 1;
        if (!string.IsNullOrEmpty(maxOrderId))
        {
            var numberPart = maxOrderId.Substring(currentDate.Length);
            if (int.TryParse(numberPart, out int numericValue))
            {
                sequenceNumber = numericValue + 1;
            }
        }

        return $"{currentDate}{sequenceNumber.ToString().PadLeft(4, '0')}";
    }
}



